import { useRef, useState } from 'react';

import { useControllableValue, useInfiniteScroll } from 'ahooks';
import { Col, Input, Result, Row, Segmented, Spin, Tree } from 'antd';
import cs from 'classnames';
import { debounce } from 'lodash-es';

import { TargetType, TimeSort } from '@/enum';
import { orgUserInfoVoPage } from '@/services/base/yonghuguanlixitongyonghujiekou';

import { Assignee, DeptDataNode, RoleDataNode, UserSelectProps } from '..';
import Avatar from '../avatar';
import styles from './index.module.scss';

export type UserPanelProps = Pick<UserSelectProps, 'value' | 'onChange' | 'mode'> & {
  /** 部门树 */
  deptTree?: DeptDataNode[];
  /** 角色列表 */
  roleList?: RoleDataNode[];
};

const UserPanel: React.FC<UserPanelProps> = ({ deptTree, roleList, mode, ...rest }) => {
  // 是否多选
  const isMultiple = mode === 'multiple' || mode === 'tags';
  const [value, setValue] = useControllableValue<UserSelectProps['value']>(rest);
  const $userList = useRef<HTMLDivElement>(null);
  // 搜索
  const [searchValue, setSearchValue] = useState('');
  // 选择的筛选类型
  const [selectType, setSelectType] = useState(TargetType.部门);
  // 选择的部门
  const [selectDept, setSelectDept] = useState<number>();
  // 选择的角色
  const [selectRole, setSelectRole] = useState<number>();

  // 用户列表
  const userList = useInfiniteScroll<{
    total: number;
    page: number;
    list: Assignee[];
  }>(
    async (query) => {
      const page = query ? query.page + 1 : 1;

      if (page === 1) {
        userList.mutate(undefined);
      }

      const pageQuery = {
        page,
        size: 10,
        timeSort: TimeSort.倒序
      } as ArgumentsType<typeof orgUserInfoVoPage>[0];

      if (searchValue) {
        pageQuery.fullName = searchValue;
      } else if (selectRole) {
        pageQuery.roleId = selectRole;
      } else if (selectDept) {
        pageQuery.deptId = selectDept;
      }

      const res = await orgUserInfoVoPage(pageQuery);

      const total = res?.data?.total || 0;
      const list = (res?.data?.records || []).map((item) => {
        return {
          ...item,
          id: item.id,
          name: item.fullName || item.username,
          type: TargetType.用户
        } as Assignee;
      });

      // const list = (query?.list || []).concat(
      //   (res?.data?.records || []).map((item) => {
      //     return {
      //       ...item,
      //       id: item.id,
      //       name: item.fullName || item.username,
      //       type: TargetType.用户
      //     } as Assignee;
      //   })
      // );

      return {
        list,
        total,
        page
      };
    },
    {
      isNoMore: (data) => {
        if (!data) {
          return false;
        }

        return data.list.length >= data.total;
      },
      target: $userList,
      reloadDeps: [searchValue, selectDept, selectRole]
    }
  );

  const onSearch = debounce(
    ((e) => {
      setSearchValue(e.target.value);
    }) as NonNullable<React.ComponentProps<typeof Input.Search>['onChange']>,
    500
  );

  const onSelected = (item: Assignee) => {
    setValue((prev) => {
      if (isMultiple) {
        if ((prev as Assignee[])?.some((v) => v.id === item.id)) {
          return (prev as Assignee[])!.filter((v) => v.id !== item.id);
        } else {
          return [...((prev as Assignee[]) || []), item];
        }
      } else {
        return (prev as Assignee | undefined)?.id === item.id ? undefined : item;
      }
    });
  };

  return (
    <div className={styles['user-panel']}>
      <Input.Search onChange={onSearch} placeholder="输入姓名查询" allowClear />
      <Row>
        <Col span={12}>
          <Segmented
            value={selectType}
            onChange={setSelectType}
            options={[
              { label: '部门', value: TargetType.部门 },
              { label: '角色', value: TargetType.角色 }
            ]}
            block
          />
          <div
            className={cs(styles['tree-container'], {
              [styles['active']]: selectType === TargetType.部门
            })}
          >
            <Tree<DeptDataNode>
              treeData={deptTree}
              blockNode
              selectable
              showLine
              selectedKeys={selectDept ? [selectDept] : []}
              onSelect={(keys) => {
                setSelectDept(keys[0] as number);
              }}
            />
          </div>
          <div
            className={cs(styles['tree-container'], {
              [styles['active']]: selectType === TargetType.角色
            })}
          >
            <Tree<RoleDataNode>
              treeData={roleList}
              blockNode
              selectable
              showLine
              selectedKeys={selectRole ? [selectRole] : []}
              onSelect={(keys) => {
                setSelectRole(keys[0] as number);
              }}
            />
          </div>
        </Col>
        <Col span={12}>
          <div ref={$userList}>
            {userList.error ? (
              <Result
                status="error"
                title="加载失败"
                subTitle={userList.error as unknown as string}
              />
            ) : (
              <>
                {userList.data?.list?.map((user) => {
                  const active = isMultiple
                    ? (value as Assignee[])?.some((v) => v.id === user.id)
                    : (value as Assignee)?.id === user.id;

                  return (
                    <div
                      className={cs(styles['user-item'], {
                        [styles['active']]: active
                      })}
                      onClick={onSelected.bind(null, user)}
                      key={user.id}
                    >
                      <Avatar>{user.name}</Avatar>
                      {user.name}
                    </div>
                  );
                })}
                {userList.noMore ? (
                  <div className={styles['no-more']}>没有更多了</div>
                ) : (
                  <div className={styles['loading']}>
                    <Spin />
                  </div>
                )}
              </>
            )}
          </div>
        </Col>
      </Row>
    </div>
  );
};

export default UserPanel;
